package com.guli.gulimall.product.web;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.guli.gulimall.product.dao.CategoryDao;
import com.guli.gulimall.product.entity.CategoryEntity;
import com.guli.gulimall.product.service.CategoryService;
import com.guli.gulimall.product.vo.Catalog2Vo;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author: 朱财艺
 * @date : 2021/12/26
 * @Description:
 */
@Controller
public class IndexController {

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private CategoryDao categoryDao;


    @RequestMapping(value = {"/","index.html"})
    public String index(Model model){

        QueryWrapper<CategoryEntity> parentCid = new QueryWrapper<CategoryEntity>().eq("parent_cid", "0");
        List<CategoryEntity> entityList = categoryDao.selectList(parentCid);
        model.addAttribute("list",entityList);
        return "index";
    }

    @RequestMapping("/findCatalog")
    @ResponseBody
    public Map<String, List<Catalog2Vo>> findCatalog(){

        return categoryService.rwLock();
    }

    @Autowired
    private RedissonClient redisson;

    //redisson锁
    @ResponseBody
    @GetMapping(value = {"/hi"})
    public String hi(){
        //获取一把锁，只要锁的名字一样，就是一把锁
        RLock lock = redisson.getLock("my-lock");

        //加锁
        lock.lock();

        //
        try {

            System.out.println("加锁成功，执行业务。。。"+Thread.currentThread().getId());

            try {
                TimeUnit.SECONDS.sleep(20);
            }catch (Exception e){
                e.printStackTrace();
            }finally {

                System.out.println("解锁"+Thread.currentThread().getId());
                //解锁
                lock.unlock();
            }


        } catch (Exception e){

            e.printStackTrace();
        }
        return "hi";

    }


    /**
     * 车库停车
     *
     * 3车位
     *
     * 信号量也可以做分布式限流
     * @return
     * @throws InterruptedException
     */
    @GetMapping("hi1")
    @ResponseBody
    public String hi1() throws InterruptedException {

        RSemaphore park = redisson.getSemaphore("park");
        park.acquire();//获取一个信号、获取一个值，占一个车位
        boolean b = park.tryAcquire();
        if (b){
            //站到车位执行业务

            TimeUnit.SECONDS.sleep(3);
        }else {

            return "error";
        }

        return "ok=>"+b;
    }

    @GetMapping("go")
    @ResponseBody
    public String go(){

        RSemaphore park = redisson.getSemaphore("park");
        park.release();//释放一个车位

        return "ok";
    }

    /**
     *
     * 读锁是读取写锁存入db的数据
     *
     * 写锁是写入redisdb数据
     */
    @Autowired
    private StringRedisTemplate redisTemplate;
    @GetMapping("write")
    @ResponseBody
    public String writeValue(){

        String s="";
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("rw-lock");
        RLock rLock = readWriteLock.writeLock();
        try {
            //改数据加写锁，读数据加读锁
            rLock.lock();
            s = UUID.randomUUID().toString();
            ValueOperations<String, String> ops = redisTemplate.opsForValue();
            ops.set("writeValue",s);
            TimeUnit.SECONDS.sleep(10);
        }catch (Exception e){

            e.printStackTrace();
        }finally {

            rLock.unlock();
        }

        return s;
    }

    @GetMapping("read")
    @ResponseBody
    public String readValue(){

        String s="";
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("rw-lock");

        //加读锁
        RLock rLock = readWriteLock.readLock();
        try {
            rLock.lock();
            ValueOperations<String, String> ops = redisTemplate.opsForValue();
            s = ops.get("writeValue");
            try {
                TimeUnit.SECONDS.sleep(10);
            }catch (Exception e){

                e.printStackTrace();
            }
        }catch (Exception e){

            e.printStackTrace();
        }finally {
            rLock.unlock();
        }

        return s;

    }

    @GetMapping("lockDoor")
    @ResponseBody
    public String lockDoor() throws InterruptedException {

        RCountDownLatch door = redisson.getCountDownLatch("door");
        door.trySetCount(5);
        door.await();

        return "放假了";
    }

    @GetMapping("/gogo/{id}")
    @ResponseBody
    public String gogogo(@PathVariable("id")Long id){

        RCountDownLatch door = redisson.getCountDownLatch("door");
        door.countDown();

        return id+"班的人都走了....";
    }




}
